

#include "vPortSimu.h" 
#include "vPPMgm.h" 
/*** Interior Define */

#define LLOG_ERR
#define LLOG_TICK
#define LLOG_MARK
#define LLOG
#include "llog.h"

#ifdef	CFG_SYS_MALLOC

#define L_MALLOC 	MALLOC
#define L_FREE 		MFREE

#else
	
	#ifdef	CFG_STATIC_BUF_ALLOCATE

	#define L_MALLOC 	SMalloc
	#define L_FREE(A) 	do{LLOG_ERR(); while(1); }while(0);

	#else 

	#include <stdlib.h>
	#define L_MALLOC(A) malloc(A)
	#define L_FREE(A)	free(A)

	#endif

#endif

/*** Interior Struct */

struct CC_vPort_Simulation_ByBFIFO{

	uint16_t State;
	
	tBFIFO* pRxFIFO;
	tBFIFO* pTxFIFO;
	
	// CoTask Var
	uint16_t RBufSz;
	uint8_t* pRBuf;
	tSTimer* pTimer;	
	
	int(*pTxFunc)(uint16_t Len,uint8_t* pPkg);
};

/*** Global Data */

/*** Local Function Define*/

//====

#ifdef CFG_VPORT_SIMU

#ifdef 	CFG_SORT_TIMER
static int CoTask_vPort_Simulation_TxGuard(void* pPara){
	
	int ret = RET_ERR;

	int RealNum;
	int i;
	tSimuPort* pObj = (tSimuPort*)pPara;
	if(pObj == NULL) { LLOG_ERR(); return ret;}
	
	if(pObj->State == 0) { return ret;}
	
	//
	RealNum =BFIFO_Read(pObj->pTxFIFO,pObj->RBufSz,pObj->pRBuf);
	if(RealNum){
		if(pObj->pTxFunc != NULL){
			pObj->pTxFunc(RealNum,pObj->pRBuf);
			ret=RET_OK;
		}
		else{
			Log_ShowArray("vPortTx",RealNum,pObj->pRBuf);
		}
	}

	return ret;
}

#endif

void SimuPort_Show(tSimuPort* pObj){
	
	if(pObj == NULL)	{LLOG_ERR(); return;}
	
	LLOG("\n====\n#I SimuPort=[0x%x]\n",pObj);
	LLOG("#I pRxFIFO    =[0x%x]\n",pObj->pRxFIFO);
	LLOG("#I pTxFIFO    =[0x%x]\n",pObj->pTxFIFO);
	LLOG("#I RBufSz     =[0x%x]\n",pObj->RBufSz);
	// LLOG("#I pRBuf      =[0x%x]\n",pObj->pRBuf);
	// LLOG("#I pTimer     =[0x%x]\n",pObj->pTimer);
	LLOG("#I pTxFunc    =[0x%x]\n",pObj->pTxFunc);
		
}

tSimuPort* SimuPort_Create(uint16_t RxTxBufSz,tMs TxPeriod,uint16_t RBufSz) {	
	tSimuPort* ptmp = NULL;
	uint8_t* pBuf = NULL;
	
	if(RxTxBufSz == 0)	{ LLOG_ERR(); return ptmp; }
	if(RBufSz  == 0)	{ LLOG_ERR(); return ptmp; }
	
	ptmp = (tSimuPort*)L_MALLOC(sizeof(tSimuPort)+RBufSz);
	if(ptmp == NULL){
		LLOG_ERR();
		return ptmp;
	}
	pBuf = (uint8_t*)ptmp;
	MEMSET((uint8_t*)ptmp,0,sizeof(tSimuPort));

	//
	ptmp->pRxFIFO = BFIFO_Create(RxTxBufSz);
	if(ptmp->pRxFIFO == NULL) {
		LLOG_ERR(); 
		L_FREE(ptmp);
		return ptmp; 
	}
	
	ptmp->pTxFIFO = BFIFO_Create(RxTxBufSz);
	if(ptmp->pTxFIFO == NULL) {
		LLOG_ERR(); 
		L_FREE(ptmp->pRxFIFO);
		L_FREE(ptmp);
		return ptmp; 
	}	

	ptmp->RBufSz = RBufSz; 
	ptmp->pRBuf = &pBuf[sizeof(tSimuPort)];
	
	#ifdef 	CFG_SORT_TIMER
	do{
		tSTimer* pTimer;
		pTimer = STimer_CreateAndAdd(0, STIMER_TYP_PERIOD, TxPeriod);
		STimer_BindCBF(pTimer,CoTask_vPort_Simulation_TxGuard);
		STimer_BindPara(pTimer, (void*)ptmp );
		
		STimer_OnOff(pTimer,1);	
		ptmp->pTimer = pTimer;
	}while(0);
	#endif
	
	//
	ptmp->State = 1; 

	return ptmp;
}

int SimuPort_RxInput(tSimuPort* pObj,uint16_t Len,uint8_t* pPkg){
	if(pObj == NULL) 	 { LLOG_ERR(); return 0;}
	if(pObj->State == 0) { return 0;}
	
	return (int)BFIFO_Write(pObj->pRxFIFO,Len,pPkg);	
}

int SimuPort_BindTxOutput(tSimuPort* pObj,int(*pTxFunc)(uint16_t,uint8_t*) ){
	int ret = RET_ERR;
	if(pObj == NULL) 	 { LLOG_ERR(); return ret;}
	
	ret=RET_OK;
	pObj->pTxFunc = pTxFunc;
	return ret;
}

#endif

#ifdef CFG_VPORT_SIMU //

int SimuPort_Write(tSimuPort* pObj,uint16_t Len ,uint8_t* pPkg){
	if(pObj == NULL) 	 { LLOG_ERR(); return 0;}
	if(pObj->State == 0) { return 0;}
	
	return (int)BFIFO_Write(pObj->pTxFIFO,Len,pPkg);
}

int SimuPort_Read (tSimuPort* pObj,uint16_t RLen,uint8_t* pRBuf){
	if(pObj == NULL) 	 { LLOG_ERR(); return 0;}
	if(pObj->State == 0) { return 0;}
	
	return (int)BFIFO_Read(pObj->pTxFIFO,RLen,pRBuf);	
}

int SimuPort_Ctrl (tSimuPort* pObj,uint16_t Cmd ,uint16_t Len,uint8_t* pPara){
	
	int ret =RET_ERR;
	if(pObj == NULL) 	 { LLOG_ERR(); return ret;}

	ret = RET_OK;
	Len=Len;
	pPara = pPara;
	switch(Cmd){
		case GCMD_STOP		:{ LLOG("#I SimuPort: STOP		\n");
			pObj->State = 0;
		}break;
		case GCMD_START		:{ LLOG("#I SimuPort: START		\n");
			pObj->State = 1;
		}break;
		case GCMD_CLEAN		:{ LLOG("#I SimuPort: CLEAN		\n");
			BFIFO_Reset(pObj->pRxFIFO);
			BFIFO_Reset(pObj->pTxFIFO);
		}break;
		// case GCMD_RESET		:{ LLOG("#I SimuPort: RESET		\n");}break;
		// case GCMD_GET_STATE	:{ LLOG("#I SimuPort: GET_STATE	\n");}break;
		default:{
			ret = RET_ERR;
		}
	}

	return ret;	
}

#endif

#ifdef CFG_VPORT_SIMU_APP // 一个应用实例
// #include "vPPMgm.h" 

static tSimuPort* g_pSPortMaster= NULL;
static tSimuPort* g_pSPortSlave	= NULL;

static int SPort_Master_Tx(uint16_t Len,uint8_t* pPkg){
	return SimuPort_RxInput(g_pSPortSlave,Len,pPkg);
}

static int SPort_Slave_Tx(uint16_t Len,uint8_t* pPkg){
	return SimuPort_RxInput(g_pSPortMaster,Len,pPkg);
}

// 
int SimuPort_MasterSlave_Init(void){
	
	int ret=RET_ERR;
	
	g_pSPortMaster = SimuPort_Create(500,100,40);
	if(g_pSPortMaster == NULL) {LLOG_ERR(); return ret;}
	
	g_pSPortSlave  = SimuPort_Create(500,100,40);
	if(g_pSPortSlave == NULL) {LLOG_ERR(); return ret;}
	
	// Bind Master and Slave;
	SimuPort_BindTxOutput(g_pSPortMaster,SPort_Master_Tx);
	SimuPort_BindTxOutput(g_pSPortSlave,SPort_Slave_Tx);
	
	
	ret=RET_OK;
	return ret;
}

int SPort_Master_Write(uint16_t Len,uint8_t* pPkg){
	return SimuPort_Write(g_pSPortMaster,Len,pPkg);
}

int SPort_Master_Read(uint16_t RLen,uint8_t* pRBuf){
	return SimuPort_Read(g_pSPortMaster,RLen,pRBuf);
}

int SPort_Master_Ctrl(uint16_t Cmd,uint16_t Len,uint8_t* pPara){
	return SimuPort_Ctrl(g_pSPortMaster,Cmd,Len,pPara);
}
//
int SPort_Slave_Write(uint16_t Len,uint8_t* pPkg){
	return SimuPort_Write(g_pSPortSlave,Len,pPkg);
}

int SPort_Slave_Read(uint16_t RLen,uint8_t* pRBuf){
	return SimuPort_Read(g_pSPortSlave,RLen,pRBuf);
}

int SPort_Slave_Ctrl(uint16_t Cmd,uint16_t Len,uint8_t* pPara){
	return SimuPort_Ctrl(g_pSPortSlave,Cmd,Len,pPara);
}

#endif



